<?php

namespace app\common\controller;

use think\facade\View;
use think\exception\HttpResponseException;
use app\common\controller\Base;
use app\common\exception\MyException;
use app\common\service\sys\ClientService;
use app\common\service\sys\DictService;
use app\common\service\sys\UserRoleMenusService;
use app\common\service\sys\UserService;

/**
 * 后台权限控制器基类
 * @author kaige
 * @copyright ©2022 泉州市盛筑信息科技有限公司 版权所有
 * @date 2022-04-25 
 */
class Basic extends Base
{
    // 设置当前服务
    protected $service;
    //用户信息
    protected $user;
    //节点
    protected $node;
    //字典
    protected $sysdict;

    /**
     * 初始化 不能用 return 只能exit
     * @return void
     */
    protected function initialize()
    {
        parent::initialize();
        //验证签名(不能放在中间件，放中间件throw错误还是会运行后面的代码)
        $appid = $this->request->header('Kg-Appid');
        if (empty($appid)) {
            throw new MyException(['code' => 1002]);
        }
        // 实时数据
        $app = (new ClientService())->getInfoByName($appid);
        // 是否存在
        if (empty($app)) {
            throw new MyException(['code' => 2001]);
        }
        // 状态
        if (empty($app) || $app['status'] != 1) {
            throw new MyException(['code' => 2002]);
        }
        // 客户端应用ID
        $this->request->client_appid = $appid;

        $appsignwhite = config("kaige.app_sign_white_url");
        list($module, $controller, $action) = [app('http')->getName(), $this->request->controller(), $this->request->action()];
        $node = $module . '/' . $controller . '/' . strtolower($action);
        $node = parseNodeStr($node); //strtolower($node);
        // throw new MyException(['code' => 1004,'msg'=>$node]); //调试用
        $this->node = $node;

        // 免签白名单
        $whilesign = false;
        if ($node && $appsignwhite && in_array($node, $appsignwhite)) {
            $whilesign = true;
        }

        // 接口签名认证
        if (config("kaige.app_sign_auth_on") === true && $whilesign === false) {
            // app端生成的签名
            $param = $this->request->param();
            $sign  = $this->request->param("signature"); //前端过来的是signature
            unset($param['signature']);
            if (empty($sign)) {
                throw new MyException(['code' => 2003,'msg'=>$node]);
            }
            //数组排序
            ksort($param);
            $str = http_build_query($param);
            $sign1 = md5(sha1($str) . $app['app_salt']);
            if ($sign != $sign1) {
                throw new MyException(['code' => 2004]);
            }
        }

        $token = $this->request->header('Kg-Token');
        if(empty($token) || $token == 'false' || $token === false){
            throw new MyException(['code' => 2101]);
            exit;
        }

        //验证身份（登录）
        $user = (new UserService())->checkAdmin($token);
        $this->user = $user['user'];

        //判断当前是否有权限操作
        $urmService = new UserRoleMenusService();
        $permRe = $urmService->checkPerm($this->user['id'], $node);
        if (!$permRe['status']) {
            if ($this->request->isGet() || $this->request->isPost()) {
                throw new MyException(['code' => 2005, 'msg' => $permRe['msg']]);
                exit;
            } else {
                $this->error($permRe['msg']);
                exit;
            }
        }

        //取出字典
        $this->sysdict = DictService::getDictAll(11);//默认 盛筑科技 ID 11
        //操作日志事件
        $param = $this->request->param();
        if(isset($param['password'])) unset($param['password']); //删除密码
        if(isset($param['pwd'])) unset($param['pwd']);//删除密码
        event('UserLog', [$this->user, $this->node, time(), _gip(),$action,json_encode($param).',ON-'.getOS().'-'.getBrowser()]);
    }

    /**
     * 操作成功跳转的快捷方法
     * @access protected
     * @param  mixed     $msg 提示信息
     * @param  string    $url 跳转的URL地址
     * @param  mixed     $data 返回的数据
     * @param  integer   $wait 跳转等待时间
     * @param  array     $header 发送的Header信息
     * @return void
     */
    protected function success($msg = '', string $url = null, $data = '', int $wait = 3, array $header = [])
    {
        if (is_null($url) && isset($_SERVER["HTTP_REFERER"])) {
            $url = $_SERVER["HTTP_REFERER"];
        } elseif ($url) {
            $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : app('route')->buildUrl($url);
        }

        $result = [
            'code' => 1,
            'msg'  => $msg,
            'data' => $data,
            'url'  => (string)$url,
            'wait' => $wait,
        ];

        $type = $this->getResponseType();
        if (strtolower($type) == 'html') {
            $response = view($this->app->config->get('app.dispatch_success_tmpl'), $result);
        } else if ($type == 'json') {
            $response = json($result);
        }
        throw new HttpResponseException($response);
    }

    /**
     * 操作错误跳转的快捷方法
     * @access protected
     * @param  mixed     $msg 提示信息
     * @param  string    $url 跳转的URL地址
     * @param  mixed     $data 返回的数据
     * @param  integer   $wait 跳转等待时间
     * @param  array     $header 发送的Header信息
     * @return void
     */
    protected function error($msg = '', string $url = null, $data = '', int $wait = 5, array $header = [])
    {
        if (is_null($url)) {
            $url = $this->request->isAjax() ? '' : 'javascript:history.back(-1);';
        } elseif ($url) {
            $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : app('route')->buildUrl($url);
        }

        $result = [
            'code' => 0,
            'msg'  => $msg,
            'data' => $data,
            'url'  => (string)$url,
            'wait' => $wait,
        ];

        $type = $this->getResponseType();
        if ($type == 'html') {
            $response = view($this->app->config->get('app.dispatch_error_tmpl'), $result);
        } else if ($type == 'json') {
            $response = json($result);
        }
        throw new HttpResponseException($response);
    }

    protected function redirect(...$args)
    {
        throw new HttpResponseException(redirect(...$args));
    }

    protected function assign(...$vars)
    {
        View::assign(...$vars);
    }

    protected function fetch(string $template = '')
    {
        return View::fetch($template);
    }

    /**
     * 获取当前的response 输出类型
     * @access protected
     * @return string
     */
    protected function getResponseType()
    {
        return $this->request->isJson() || $this->request->isAjax() ? 'json' : 'html';
    }
}
